﻿using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Web.Mvc;
using EzDesk.Apps.Interface.Attendance;
using EzDesk.Apps.ServiceImpl.Attendance;
using EzDesk.Utility.Extensions;
using EzDesk.Utility.Web.Extensions;
using EzDesk.Utility.Web.Controllers;
using EzDesk.Apps.Model.Attendance;
using EzDesk.Utility;
using EzDesk.Clients.DesktopWeb.Attendance.ViewModel;
using EzDesk.Utility.Log;
using EzDesk.Utility.Web.ServiceReference;
using EzDesk.Utility.ServiceStatusInfo;

namespace EzDesk.Clients.DesktopWeb.Controllers
{
    [Authorize]
    public class AttendanceController : EzDeskAppController
    {
        private readonly IAttendanceService _attendanceService = new AttendanceService();
        IAttendanceService AttendanceService
        {
            get { return _attendanceService; }
        }

        #region [ Page Method ]
        //
        // GET: /Attendance/CheckAttendance

        [Authorize]
        public ActionResult CheckAttendance(string state, string info)
        {
            var currentTime = DateTime.Now;
            var attendanceConfig = AttendanceService.GetAttendanceConfig().Result;

            var ondutyTimeForward = attendanceConfig.StdOnDutyTime.ToDateTime() - attendanceConfig.OnDutyOffsetForward;
            var ondutyTimeDelay = attendanceConfig.StdOnDutyTime.ToDateTime() + attendanceConfig.StdOnDutyTimeDelay;
            var offdutyTimeForward = attendanceConfig.StdOffDutyTime.ToDateTime() - attendanceConfig.OnDutyOffsetForward;
            var offdutyTimeDelay = attendanceConfig.StdOffDutyTime.ToDateTime() + attendanceConfig.StdOnDutyTimeDelay;

            var attendanceConfigModel = new
                                            {
                                                ondutyTimeForward = ondutyTimeForward.ToShortTimeString(),
                                                ondutyTimeDelay = ondutyTimeDelay.ToShortTimeString(),
                                                offdutyTimeForward = offdutyTimeForward.ToShortTimeString(),
                                                offdutyTimeDelay = offdutyTimeDelay.ToShortTimeString(),
                                            };

            var currentDefaultAtendanceType = getDefaultAttendanceStatus();

            ViewData["AttendanceConfig"] = attendanceConfigModel.ToJson();
            ViewData["IsAbnormal"] = currentDefaultAtendanceType.IsAbnormal ? "true" : "false";
            ViewData["IsDuplicated"] = currentDefaultAtendanceType.IsDuplicated ? "true" : "false";
            ViewData["CurrentDefaultAttendance"] = currentDefaultAtendanceType.AttendanceType;
            ViewData["DayInfo"] = AttendanceService.GetDayInfo(CurrentUserId, currentTime).Result.ToJson();

            ViewData["CurrentTime"] = getEpochForJavascript(currentTime);
            ViewData["CurrentUser"] = EzApiClient.GetSimpleUserById(CurrentUserId).ToJson();

            return View();
        }


        //
        // GET: /Attendance/ApplyLeave

        [Authorize]
        [HttpGet]
        public ActionResult ApplyLeave()
        {
            ViewData["LeaveTypeList"] = AttendanceService.GetAllLeaveTypes().Result.ToJson();
            ViewData["CurrentTime"] = getEpochForJavascript(DateTime.Now);
            ViewData["UserId"] = CurrentUserId.ToString();
            return View();
        }

        //
        // GET: /Attendance/PersonalAttendanceList

        [Authorize]
        [HttpGet]
        public ActionResult AttendanceInfoListPerMonth(long? time, Guid? userId)
        {
            DateTime date = getDateByDefault(time);

            if (!userId.HasValue)
            {
                userId = CurrentUserId;
            }
            var currentUser = EzApiClient.GetSimpleUserById(userId.GetValueOrDefault());


            var permissionStr = "ATTENDANCE_HR_MANAGEMENT";
            var isHasPermisson = IsHasPermisson(permissionStr, CurrentUserId);
            LogEx.TRACE("DesktopWeb - Attendance",
                        "IsHasPermission: " + permissionStr + " " + userId.Value + " " + isHasPermisson.ToString());

            ViewData["IsHasPermisson"] = isHasPermisson.ToJson();
            ViewData["StartYear"] = "2009";
            ViewData["TargetTime"] = getEpochForJavascript(date);
            ViewData["CurrentTime"] = getEpochForJavascript(DateTime.Now);
            ViewData["CurrentDeptList"] = EzApiClient.GetAllDepts().ToJson();
            ViewData["CurrentUser"] = currentUser.ToJson();
            return View();
        }

        //
        // GET: /Attendance/PersonalLeaveInfoList

        [Authorize]
        public ActionResult PersonalLeaveInfoList(long? time, Guid? userId)
        {
            DateTime date = getDateByDefault(time);
            if (!userId.HasValue)
            {
                userId = CurrentUserId;
            }
            var currentUser = EzApiClient.GetSimpleUserById(userId.GetValueOrDefault());

            var permissionStr = "ATTENDANCE_HR_MANAGEMENT";
            var isHasPermisson = IsHasPermisson(permissionStr, CurrentUserId);

            ViewData["IsHasPermisson"] = isHasPermisson.ToJson();
            ViewData["CurrentTime"] = getEpochForJavascript(date);
            ViewData["CurrentDeptList"] = EzApiClient.GetAllDepts().ToJson();
            ViewData["CurrentUser"] = currentUser.ToJson();

            return View();
        }

        //
        // GET: /Attendance/AuditLeave
        [Authorize]
        [PermissionRequireAttribute("ATTENDANCE_HR_MANAGEMENT")]
        public ActionResult AuditLeave(Guid leaveId, bool? isAgree, string target)
        {
            // 处理直接审批
            if (target == "action")
            {
                return DoAuditLeave(leaveId, isAgree.GetValueOrDefault(false), "");
            }

            LeaveInfo leaveInfo = AttendanceService.GetLeaveInfoById(leaveId).Result;
            ViewData["LeaveInfo"] = leaveInfo.ToJson();

            return View();
        }

        //
        // GET: /Attendance/AuditList
        [Authorize]
        [HttpGet]
        [PermissionRequireAttribute("ATTENDANCE_HR_MANAGEMENT")]
        public ActionResult AuditList()
        {
            ViewData["StartYear"] = "2009";
            ViewData["CurrentTime"] = getEpochForJavascript(DateTime.Now);
            ViewData["CurrentUser"] = EzApiClient.GetSimpleUserById(CurrentUserId).ToJson();

            return View();
        }



        [HttpGet]
        public ActionResult PersonalAttendanceInfoList(long? time, Guid? userId)
        {
            var date = getDateByDefault(time);
            if (!userId.HasValue)
            {
                userId = CurrentUserId;
            }
            var currentUser = EzApiClient.GetSimpleUserById(userId.GetValueOrDefault());

            const string permissionStr = "ATTENDANCE_HR_MANAGEMENT";
            var isHasPermisson = IsHasPermisson(permissionStr, CurrentUserId);

            ViewData["IsHasPermisson"] = isHasPermisson.ToJson();
            ViewData["CurrentTime"] = getEpochForJavascript(date);
            ViewData["CurrentDeptList"] = EzApiClient.GetAllDepts().ToJson();
            ViewData["CurrentUser"] = currentUser.ToJson();

            return View();
        }


        /// <summary>
        /// 人事查看某日考勤情况汇总页面
        /// </summary>
        /// <param name="time">要显示页面的时间</param>
        /// <returns></returns>
        [Authorize]
        [HttpGet]
        [PermissionRequireAttribute("ATTENDANCE_HR_MANAGEMENT")]
        public ActionResult AttendanceInfoListPerDayManager(long? time)
        {
            LogEx.TRACE("DesktopClient - Attendance", "开始AttendanceInfoListPerDayManager请求");
            var isDisplayEvaluationInfo = "true";
            var isDisplayAttendanceInfo = "false";
            // 获取页面要显示的内容日期
            DateTime date = getDateByDefault(time);

            // 获取当日的dayInfo
            var dayInfo = AttendanceService.GetDayInfo(CurrentUserId, date).Result;
           
            // 获取当日所有员工的考勤详细情况
            var allUserList = EzApiClient.GetSimpleUserInfos("everyone");
            var userList = new List<Guid>{};
            foreach (var user in allUserList)
            {
                userList.Add(user.Id);
            }
            var remarks = AttendanceService.GetAttendanceRemarkListByUsersInDay(date, userList).Result;
            var dayAttendanceDetailList = allUserList.Select(
                user =>
                {
                    var attendanceEvaluation = AttendanceService.GetDayAttendanceEvaluation(user.Id, date).Result.FirstOrDefault();
                    if(date == DateTime.Now.Date)
                    {
                        attendanceEvaluation.IsAbsense = false;
                    }
                    var applicationStr = AttendanceService
                            .GetCurrentEvaluationModifyApplication(user.Id.ToString(), date)
                            .Result.FirstOrDefault()
                            .GetCurrentApplicationString();
                    var modifyHistory = AttendanceService.GetDayLatestEvaluationModifyHistory(user.Id.ToString(), date).Result;
                    return new
                               {
                                   TargetUser = user,
                                   AttendanceInfoList = attendanceEvaluation.DayAttendanceInfoList,
                                   LeaveInfo = attendanceEvaluation.LeaveInfo,
                                   Application = applicationStr,
                                   ModifyHistoryStr = modifyHistory
                                            .FirstOrDefault(p => p.Date == date)
                                            .GetLatestModifyHistroyString(),
                                   EvaluationStr = attendanceEvaluation.GetEvaluationStatusString(),
                                   EvaluationClassName = attendanceEvaluation.GetEvaluationStatusClassName(),
                                   RemarkInfo = remarks.Where(p=> p.UserId == user.Id).ToList().FirstOrDefault(),
                               };
                })
                .ToList()
                .OrderBy(p=>p.EvaluationClassName);

            //当日日期
            var currentDate = DateTime.Now.Date;
            //如果是当日不显示考勤评估信息
            if (currentDate == dayInfo.Date)
            {
                isDisplayEvaluationInfo = "false";
            }

            //非将来时间
            if (currentDate >= dayInfo.Date)
            {
                isDisplayAttendanceInfo = "true";

                ViewData["IsDisplayEvaluationInfo"] = isDisplayEvaluationInfo;
                ViewData["DayAttendanceDetailList"] = dayAttendanceDetailList.ToJson();
            }

            ViewData["DayInfo"] = dayInfo.ToJson();
            ViewData["IsDisplayAttendanceInfo"] = isDisplayAttendanceInfo;
            LogEx.TRACE("DesktopClient - Attendance", "返回AttendanceInfoListPerDayManager请求");
            return View();
        }



        /// <summary>
        /// 人事修改某日某人考勤情况页面
        /// </summary>
        /// <param name="time">要显示页面的时间</param>
        /// <param name="userId">目标用户的Id</param>
        /// <returns></returns>
        [Authorize]
        [PermissionRequireAttribute("ATTENDANCE_HR_MANAGEMENT")]
        public ActionResult ModifyAttendanceInfoPerDay(long? time, Guid userId)
        {
            // 获取页面要显示的内容日期
            DateTime date = getDateByDefault(time);

            // 获取当日dayInfo
            DayInfo dayInfo = AttendanceService.GetDayInfo(userId, date).Result;
            // 考勤备注
            var remarkInfo = AttendanceService.GetAttendanceRemarkListByUserInDay(date, userId).Result.FirstOrDefault();
            //考勤评估
            var evalution = AttendanceService.GetDayAttendanceEvaluation(userId, date).Result.FirstOrDefault();
            // 当日考勤详细信息
            var dayAttendanceDetail = new
            {
                TargetUser = EzApiClient.GetSimpleUserById(userId),
                AttendanceEvaluation = evalution,
                RemarkInfo = remarkInfo
            };

            //当日日期
            var currentDate = DateTime.Now.Date;
            //处理当天的矿工
            if (currentDate == dayInfo.Date)
            {
                dayAttendanceDetail.AttendanceEvaluation.IsAbsense = false;
            }

            // 获取正在提交中的评估修改申请
            var modifyAttendanceApplication = AttendanceService.GetCurrentEvaluationModifyApplication(userId.ToString(), date).Result.FirstOrDefault();

            // 获得考勤评估修改的历史信息
            var evaluationModifyHistory = AttendanceService.GetEvaluationModifyHistory(userId, date).Result;
            ViewData["CurrentDate"] = getEpochForJavascript(currentDate);
            ViewData["ModifyAttendanceApplication"] = modifyAttendanceApplication.ToJson();
            ViewData["DayAttendanceDetail"] = dayAttendanceDetail.ToJson();
            ViewData["EvaluationModifyHistory"] = evaluationModifyHistory.ToJson();
            // 默认显示自己的信息
            ViewData["TargetUser"] = EzApiClient.GetSimpleUserById(userId).ToJson();
            ViewData["DayInfo"] = dayInfo.ToJson();

            return View();
        }

        /// <summary>
        /// 显示个人某一天的考勤情况
        /// </summary>
        /// <param name="time">要显示的时间，Epoch格式</param>
        /// <returns></returns>
        [Authorize]
        public ActionResult PersonalAttendanceInfoPerDay(long? time, bool? isApplying = false)
        {
            var userId = CurrentUserId;
            // 获取页面要显示的内容日期
            var date = getDateByDefault(time);
            //当日日期
            var currentDate = DateTime.Now.Date;

            //是否可以申请修改
            var isDisplayApplyEvaluation = "true";
            //是否显示考勤是信息
            var isDisplayAttendanceInfo = "false";
            //是否显示考勤的评估信息
            var isDisplayEvaluationInfo = "true";
            //是否正在申请
            var isApplyingModify = "false";
            if (isApplying == true)
            {
                isApplyingModify = "true";
            }
            // 获取当日dayInfo
            var dayInfo = AttendanceService.GetDayInfo(userId, date).Result;
            // 获取当日考勤备注
            var remarkInfo = AttendanceService.GetAttendanceRemarkListByUserInDay(date, userId).Result.FirstOrDefault();
            // 获取正在提交中的评估修改申请
            var modifyAttendanceApplication = AttendanceService.GetCurrentEvaluationModifyApplication(userId.ToString(), date).Result.FirstOrDefault();
            //考勤评估
            var evalution = AttendanceService.GetDayAttendanceEvaluation(userId, date).Result.FirstOrDefault();
            // 当日考勤详细信息
            var dayAttendanceDetail = new 
            {
                TargetUser = EzApiClient.GetSimpleUserById(userId),
                AttendanceEvaluation = evalution,
                RemarkInfo = remarkInfo
            };


            // 获得考勤评估修改的历史信息
            var evaluationModifyHistory = AttendanceService.GetEvaluationModifyHistory(userId, date).Result;


            //如果已经申请修改或者是当天,不可再次申请
            if (modifyAttendanceApplication != null || currentDate == dayInfo.Date)
            {
                isDisplayApplyEvaluation = "false";
            }

            //如果是当日不显示考勤评估信息
            if (currentDate == dayInfo.Date)
            {
                isDisplayEvaluationInfo = "false";
            }

            //非将来时间
            if (currentDate >= dayInfo.Date)
            {
                isDisplayAttendanceInfo = "true";
                //显示考勤先关信息
                ViewData["ModifyAttendanceApplication"] = modifyAttendanceApplication.ToJson();
                ViewData["DayAttendanceDetail"] = dayAttendanceDetail.ToJson();
                ViewData["EvaluationModifyHistory"] = evaluationModifyHistory.ToJson();
                ViewData["IsDisplayApplyEvaluation"] = isDisplayApplyEvaluation;
                ViewData["IsDisplayEvaluationInfo"] = isDisplayEvaluationInfo;
                ViewData["IsApplyingModify"] = isApplyingModify;
            }

            ViewData["IsDisplayAttendanceInfo"] = isDisplayAttendanceInfo;
            ViewData["DayInfo"] = dayInfo.ToJson();
            ViewData["TargetUser"] = EzApiClient.GetSimpleUserById(userId).ToJson();

            return View();
        }


        #endregion

        #region [ Ajax Methods ]



        #region 考勤评估相关
        

        //
        // POST: /Attendance/ApplyModifyAttendanceEvaluation
        /// <summary>
        /// 提交修改考勤评估的申请
        /// </summary>
        /// <returns></returns>
        [Authorize]
        public JsonResult ApplyModifyAttendanceEvaluation(
            Guid applyUserId,
            int date,
            string applyText
            )
        {
            var theDate = EpochDateTimeExtension.FromEpoch(date);
            var statusInfo = AttendanceService.ApplyEvaluationModify(
                applyUserId,
                theDate,
                applyText
                );
            if (statusInfo.Status == ServiceStatus.Success)
            {
                statusInfo.Info = "考勤评估更改申请成功";
            }
            return Json(statusInfo);
        }

        // 
        // POST: /Attendance/ModifyAttendanceEvaluation
        /// <summary>
        /// 修改某人的考勤评估
        /// </summary>
        /// <param name="targetUserId"></param>
        /// <param name="date"></param>
        /// <param name="lateMiniutes"></param>
        /// <param name="leaveEarlyMiniutes"></param>
        /// <param name="isAbsense"></param>
        /// <param name="isExtraWork"></param>
        /// <param name="manHours"></param>
        /// <returns></returns>
        [Authorize]
        [HttpPost]
        public JsonResult ModifyAttendanceEvaluation(
            Guid targetUserId, int date,
            int? lateMiniutes,
            int? leaveEarlyMiniutes,
            bool? isAbsense,
            bool? isExtraWork,
            int? manHours
            )
        {
            var theDate = EpochDateTimeExtension.FromEpoch(date);
            var newEvaluation = AttendanceService.GetDayAttendanceEvaluation(targetUserId, theDate).Result.FirstOrDefault();

            if (lateMiniutes != null)
            {
                newEvaluation.LateMiniutes = lateMiniutes.Value;
            }
            if (leaveEarlyMiniutes != null)
            {
                newEvaluation.EarlyMiniutes = leaveEarlyMiniutes.Value;
            }
            if (isAbsense != null)
            {
                newEvaluation.IsAbsense = isAbsense.Value;
            }
            if (isExtraWork != null)
            {
                newEvaluation.IsExtraWork = isExtraWork.Value;
            }
            if (manHours != null)
            {
                newEvaluation.Manhours = manHours.Value;
            }

            var statusInfo = AttendanceService.ModifyEvaluation(newEvaluation, CurrentUserId);
            if (statusInfo.Status == ServiceStatus.Success)
            {
                statusInfo.Info = "考勤评估修改完成";
            }
            return Json(statusInfo);
        }

        
        //POST: /Attendance/RejectEvaluationApplication
        /// <summary>
        /// 拒绝某人的考勤评估
        /// </summary>
        /// <param name="applicationId"></param>
        /// <returns></returns>
        public ActionResult RejectEvaluationApplication(Guid applicationId)
        {
            var statusInfo = AttendanceService.RejectEvaluationApplication(CurrentUserId, applicationId);
            if (statusInfo.Status == ServiceStatus.Success)
            {
                statusInfo.Info = "已经拒绝了该修改申请";
            }
            return Json(statusInfo, JsonRequestBehavior.AllowGet);
        }
        #endregion

        #region 打考勤相关

        // GET: /Attendance/CurrentTimeFromServer

        /// <summary>
        /// 获得当前系统的服务端时间
        /// </summary>
        /// <returns></returns>
        [Authorize]
        [HttpGet]
        public JsonResult CurrentTimeFromServer()
        {
            var currentTime = DateTime.Now.ToEpoch();

            return Json(
                new { CurrentTime = currentTime },
                JsonRequestBehavior.AllowGet
                );
        }

        //
        // POST: /Attendance/DoCheckAttendance
        [Authorize]
        public JsonResult DoCheckAttendance(string attendanceTypeStr, string explainText)
        {
            var attendanceType = EnumExt.ParseEnum<AttendanceType>(attendanceTypeStr);
            var userId = CurrentUserId;
            var dateTime = DateTime.Now;

            var statusInfo = AttendanceService.CheckAttendance(
                userId,
                dateTime,
                attendanceType,
                explainText
                );

            if (statusInfo.Status == ServiceStatus.Success)
            {
                if (attendanceType == AttendanceType.onDuty)
                {
                    statusInfo.Info = " OK! 您已经于 " + dateTime + " 完成上班考勤.  " + " 祝您一天工作愉快！";
                }
                else
                {
                    statusInfo.Info = " 辛苦了! 您已经于 " + dateTime + " 完成下班考勤. " + " 好好休息迎接新的一天！";
                }
            }

            //此次考勤已经正常完成
            return Json(statusInfo);
        }


        /// <summary>
        /// 自动考勤的特殊方法
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="time"></param>
        /// <returns></returns>
        //[Authorize]
        public JsonResult DoAutoCheckAttendance(Guid userId, int time)
        {
            StatusInfo statusInfo;
            try
            {
                var actionTime = EpochDateTimeExtension.FromEpoch(time);

                var defaultStatus = AttendanceService.GetDefaultAttendanceStatus(userId, actionTime).Result;
                if (defaultStatus.IsAbnormal)
                {
                    // 如果现在属于正常考勤，那么记录一次上班
                    throw new Exception(actionTime.ToString() + " 这个时间不是正常考勤时间，自动考勤无效");
                }
                if (defaultStatus.IsDuplicated)
                {
                    throw new Exception(actionTime.ToString() + " 这个时间重复考勤了");
                }
                statusInfo = AttendanceService.CheckAttendance(userId, actionTime, defaultStatus.AttendanceType,
                                                               "***门禁自动考勤***");
                if (statusInfo.Status == ServiceStatus.Success)
                {
                    statusInfo.Info = defaultStatus.AttendanceType.ToString();
                }
            }
            catch (Exception ex)
            {
                statusInfo = new StatusInfo(ex);
            }

            return Json(statusInfo, JsonRequestBehavior.AllowGet);
        }


        //
        // GET: /Attendnace/CurrentDefaultAttendanceStatus

        /// <summary>
        /// 获取当前的合法考勤类型以及考勤状态
        /// </summary>
        /// <returns></returns>
        [Authorize]
        [HttpGet]
        public JsonResult CurrentDefaultAttendanceStatus()
        {
            return Json(
               getDefaultAttendanceStatus(),
               JsonRequestBehavior.AllowGet
               );
        }


        //
        // GET: /Attendnace/AttendanceTypeStatus

        /// <summary>
        /// 传入一个考勤类型，获取当前时间考勤状态，包括是否非正常考勤，是否重复考勤等
        /// </summary>
        /// <returns></returns>
        [Authorize]
        [HttpGet]
        public JsonResult AttendanceTypeStatus(string attendanceTypeStr)
        {
            var attendanceType = EnumExt.ParseEnum<AttendanceType>(attendanceTypeStr);
            var currentAttendanceType = AttendanceService.GetAttendanceStatus(CurrentUserId, DateTime.Now, attendanceType).Result;

            return Json(
                currentAttendanceType,
                JsonRequestBehavior.AllowGet
                );
        }

        #endregion

        #region 每日考勤备注相关
        public JsonResult GetAttendanceRemarkTheDayForUser(Guid userId, int time)
        {

            var day = EpochDateTimeExtension.FromEpoch(time);
            var remark = AttendanceService.GetAttendanceRemarkListByUserInDay(day, userId)
                .Result;

            return Json(remark, JsonRequestBehavior.AllowGet);
        }

        public JsonResult UpdateRemarkTheday(Guid userId, int time, string remark)
        {
            var day = EpochDateTimeExtension.FromEpoch(time);
            var remarkModel = AttendanceService.GetAttendanceRemarkListByUserInDay(day, userId)
                .Result;

            var statusInfo = AttendanceService.UpdateAttendanceRemarkInDay(userId, day, remark);
            if (statusInfo.Status == ServiceStatus.Success)
            {
                statusInfo.Info = "更新考勤备注完成";
            }

            return Json(statusInfo);
        }
        #endregion

        #region 假期操作相关
        //
        // POST: /Attendance/DoApplyLeave

        [Authorize]
        public ActionResult DoApplyLeave(int dateTimeBegin, int dateTimeEnd, Guid leaveTypeId, string description)
        {
            var startTime = EpochDateTimeExtension.FromEpoch(dateTimeBegin);
            var endTime = EpochDateTimeExtension.FromEpoch(dateTimeEnd);
            var leaveTypeInfo = AttendanceService.GetLeaveTypeyById(leaveTypeId).Result;

            var newLeaveInfo = new LeaveInfo()
            {
                StartTime = startTime,
                EndTime = endTime,
                Description = description,
                LeaveTypeId = leaveTypeInfo.Id,
                LeaveTypeName = leaveTypeInfo.LeaveTypeName,
                UserId = CurrentUserId,
                IsAudited = false,
            };

            var statusInfo = AttendanceService.ApplyLeave(newLeaveInfo);
            if (statusInfo.Status == ServiceStatus.Success)
            {
                statusInfo.Info = "您已经申请了 " + leaveTypeInfo.LeaveTypeName + " 请等待审核。。";
            }

            return Json(statusInfo);
        }

        // 
        // POST: /Attendance/DoAuditLeave

        [Authorize]
        [HttpPost]
        public ActionResult DoAuditLeave(Guid leaveInfoId, bool isAgreed, string auditNote)
        {
            var statusInfo = AttendanceService.AuditLeave(leaveInfoId, isAgreed, auditNote, CurrentUserId);
            if (statusInfo.Status == ServiceStatus.Success)
            {
                statusInfo.Info = "完成审批";
                statusInfo.Data = new { leaveId = leaveInfoId };
            }
            return Json(statusInfo);
        }

        #endregion





        /// <summary>
        /// 获取某一天中所有考勤人员的列表
        /// </summary>
        /// <param name="dutyType">考勤类型</param>
        /// <param name="dateEpoch">考勤日期的Epoch值</param>
        /// <returns></returns>
        [Authorize]
        [HttpGet]
        public JsonResult AttendanceListPerDay(string attendanceTypeStr, int dateEpoch)
        {
            var attendanceType = EnumExt.ParseEnum<AttendanceType>(attendanceTypeStr);
            var date = EpochDateTimeExtension.FromEpoch(dateEpoch);

            var attendanceInfoList = AttendanceService.GetAttendanceInfoListByUsersInDay(
                date,
                attendanceType: attendanceType,
                userIdList: null
                ).Result.OrderByDescending(x => x.ActionTime)
                .ToList();

            return Json(
                new
                {
                    AttendanceInfoList = convertAttendanceInfoListToModel(attendanceInfoList)
                },
                JsonRequestBehavior.AllowGet
                );
        }

        //
        // GET: /Attendance/PersonalAttendanceListPerMonth

        /// <summary>
        /// 获得某人一个月内的考勤状况
        /// </summary>
        /// <param name="currentYear">要获得数据的年份</param>
        /// <param name="currentMonth">要获得数据的月份</param>
        /// <returns></returns>
        [Authorize]
        [HttpGet]
        public JsonResult PersonalAttendanceListPerMonth(int currentYear, int currentMonth, Guid? userId)
        {
            if (!userId.HasValue)
            {
                userId = CurrentUserId;
            }
            // 提供 按日期的所有内容
            // 先得到这个月这个人的所有考勤记录
            var startDate = new DateTime(currentYear, currentMonth, 1);
            var endDate = (new DateTime(currentYear, currentMonth+1, 1)).AddDays(-1);
            endDate = endDate < DateTime.Today ? endDate : DateTime.Today;
            var dayInfos = AttendanceService.GetDayInfos(userId.Value, startDate.Date, endDate.Date).Result;
            var monthAttendanceInfoList = new List<dynamic>();
            var remarks = AttendanceService.GetAttendanceRemarkListByUserBetweenDays(startDate.Date, endDate.Date, userId.Value).Result;
            var modifyHistorys = AttendanceService.GetDayLatestEvaluationModifyHistorys(userId.ToString(), startDate.Date, endDate.Date).Result;

            for (int i = 0; i < dayInfos.Count;i++ )
            {
                var theDayInfo = dayInfos[i];
                var theDay = theDayInfo.Date;
                if (theDay > DateTime.Now.Date) continue;
                // 申请记录
                var applicationStr = AttendanceService
                    .GetCurrentEvaluationModifyApplication(userId.ToString(), theDay)
                    .Result.FirstOrDefault()
                    .GetCurrentApplicationString();

                // 考勤评估
                var attendanceEvaluation = AttendanceService.GetDayAttendanceEvaluation(userId.Value, theDay).Result.FirstOrDefault();
                attendanceEvaluation.Manhours = attendanceEvaluation.Manhours.ToManhours();
                var dayAttendanceInfoListTheDay = new
                {
                    theDayInfo,
                    AttendanceInfoList = attendanceEvaluation.DayAttendanceInfoList,
                    LeaveInfo = attendanceEvaluation.LeaveInfo,
                    Application = applicationStr,
                    ModifyHistoryStr = modifyHistorys
                                           .FirstOrDefault(p => p.Date == theDay)
                                           .GetLatestModifyHistroyString(),
                    EvaluationStr = attendanceEvaluation.GetEvaluationStatusString(),
                    //这里的处理逻辑有问题，导致leave的类型不是fc-leave的clasName
                    //TODO:bug
                    EvaluationClassName = attendanceEvaluation.GetEvaluationStatusClassName(),
                    RemarkInfo = remarks.Where(p => p.Date == theDay).ToList().FirstOrDefault(),
                    attendanceEvaluation.IsAbsense
                };


                monthAttendanceInfoList.Add(dayAttendanceInfoListTheDay);
            }


            var attendanceEvaluationList =
                AttendanceService.GetDayAttendanceEvaluations(userId.Value, startDate, endDate).Result;



            var absenseDayCount = attendanceEvaluationList.Count(p => p.IsAbsense);
            var leaveDayCount = attendanceEvaluationList.Count(p => p.LeaveInfo.IsWholeDay);
            var workDayCount = attendanceEvaluationList.Count(p => !p.IsAbsense && !p.LeaveInfo.IsWholeDay && p.IsNeedToWork);

            var lateDayCount = attendanceEvaluationList.Count(p => p.IsLate);
            var overtimeDayCount = attendanceEvaluationList.Count(
                p =>
                    {
                        var attendanceList = p.DayAttendanceInfoList.OrderBy(att => att.ActionTime);
                        if (attendanceList.LastOrDefault() == null) return false;
                        return attendanceList.Last().ActionTime.TimeOfDay >= TimeSpan.FromMinutes(20*60 + 30);
                    });
            var extraManhoursInMonth = attendanceEvaluationList
                .Where(p => p.IsExtraWork)
                .Sum(p => p.Manhours);
            var extraFoodInMonth = attendanceEvaluationList
                .Count(p => p.IsExtraWork && p.Manhours >= 4 * 60);            

            dynamic result = new ExpandoObject();
            result.MonthAttendanceInfoList = monthAttendanceInfoList;

            result.OvertimeDayCount = overtimeDayCount;
            result.LateDayCount = lateDayCount;
            result.ExtraManhoursInMonth = extraManhoursInMonth;
            result.ExtraFoodInMonth = extraFoodInMonth;
            result.AbsenseDayCount = absenseDayCount;
            result.LeaveDayCount = leaveDayCount;
            result.WorkDayCount = workDayCount;

            return Json(
                result,
                JsonRequestBehavior.AllowGet
                );
        }


        /// <summary>
        /// 获取审批用的假期列表
        /// </summary>
        /// <param name="isShowAuditedLeave">是否包括出已经审核的假期</param>
        /// <param name="currentMonth">对于已审核的假期显示的月份</param>
        /// <param name="currentYear">对于已审核的假期显示的年份</param>
        /// <returns></returns>
        [Authorize]
        [HttpGet]
        public JsonResult LeaveInfoListForAudit(bool isShowAuditedLeave, int? currentMonth, int? currentYear)
        {
            var startDate = DateTime.Now.AddYears(-1);
            var endDate = DateTime.Now;
            var result = new List<LeaveInfo>();
            // 先获得所有还没有审核的假期条目
            var notAuditedLeaveList = AttendanceService.GetLeaveInfoList(
                null,
                null,
                createTimeStart: startDate,
                createTimeEnd: endDate,
                userId: null,
                isAgreed: null,
                isAudited: false
                ).Result;
            result.AddRange(notAuditedLeaveList);

            // 如果需要，获得已经审核的假期条目
            if (isShowAuditedLeave)
            {
                if (!currentYear.HasValue)
                {
                    throw new Exception();
                }
                if (!currentMonth.HasValue)
                {
                    throw new Exception();
                }

                startDate = new DateTime(currentYear.Value, currentMonth.Value, 1);
                endDate = startDate.AddMonths(1).AddDays(-1);
                var auditedLeaveList = AttendanceService.GetLeaveInfoList(
                    null,
                    null,
                    createTimeStart: startDate,
                    createTimeEnd: endDate,
                    userId: null,
                    isAgreed: null,
                    isAudited: null
                    ).Result;
                result = auditedLeaveList;
            }

            return Json(
                result,
                JsonRequestBehavior.AllowGet
                );
        }

        // 
        // GET: /Attendance/LeaveInfoById
        [HttpGet]
        public JsonResult LeaveInfoById(Guid leaveId)
        {
            var leaveInfo = AttendanceService.GetLeaveInfoById(leaveId).Result;
            return Json(
                leaveInfo,
                JsonRequestBehavior.AllowGet
                );
        }

        //
        // GET: /Attendance/PersonalLeaveInfoListPerYear
        [HttpGet]
        public JsonResult PersonalLeaveInfoListPerYear(int currentDate, Guid? userId)
        {
            if (!userId.HasValue)
            {
                userId = CurrentUserId;
            }
            var date = EpochDateTimeExtension.FromEpoch(currentDate);
            var startTime = new DateTime(date.Year, 1, 1);
            var endTime = new DateTime(date.Year + 1, 1, 1).AddHours(-1);

            // 返回所有审核已通过 或者 未审核 的记录
            var leaveInfoList = AttendanceService.GetLeaveInfoList(
                startTime, endTime,
                createTimeStart: null,
                createTimeEnd: null,
                userId: userId,
                isAudited: null,
                isAgreed: null
                ).Result;

            return Json(
                convertLeaveInfoListToSimpleModel(leaveInfoList),
                JsonRequestBehavior.AllowGet
                );
        }


        /// <summary>
        /// 员工查看个人一年考勤情况
        /// </summary>
        /// <param name="time"></param>
        /// <param name="userId"></param>
        /// <returns></returns>
        [HttpGet]
        public JsonResult PersonalAttendanceInfoListPerMonth(int time, Guid? userId)
        {
            LogEx.TRACE("AttendanceController - PersonalAttendanceInfoListPerMonth", "请求拿一个用户一个月的考勤记录开始。。。");

            if (!userId.HasValue)
            {
                userId = CurrentUserId;
            }

            var date = EpochDateTimeExtension.FromEpoch(time);
            var month = date.Month;
            var year = date.Year;
            var startDate = new DateTime(year, month, 1);
            var endDate = startDate.AddMonths(1).AddDays(-1);

            var monthAttendanceInfoList = new List<dynamic>();
            //日历数据
            var infoForCalendarList = new List<dynamic>();
            //每天的考勤详情
            var attendanceInfoPerDayList = new List<dynamic>();
            LogEx.TRACE("AttendanceController - PersonalAttendanceInfoListPerMonth", "开始WebService请求。。。");

            var modifyHistorys =  AttendanceService.GetDayLatestEvaluationModifyHistorys(userId.ToString(), startDate.Date, endDate.Date).Result;
            var attendanceEvaluations = AttendanceService.GetDayAttendanceEvaluations(userId.Value, startDate.Date, endDate.Date).Result;
            var remarks = AttendanceService.GetAttendanceRemarkListByUserBetweenDays(startDate, endDate, userId.Value).Result;
            var modifyAttendanceApplications = AttendanceService.GetCurrentEvaluationModifyApplications(userId.ToString(), startDate.Date, endDate.Date).Result;
            var dayInfos = AttendanceService.GetDayInfos(userId.Value, startDate.Date, endDate.Date).Result;

            LogEx.TRACE("AttendanceController - PersonalAttendanceInfoListPerMonth", "结束WebService请求。。。");

            foreach (var theDayInfo in dayInfos)
            {
                var theDay = theDayInfo.Date;
                //将来时间
                if (theDay > DateTime.Now) continue;

                // 考勤备注
                var remarkInfo = remarks.Where(p => p.Date == theDay).ToList().FirstOrDefault();

                //考勤评估
                var attendanceEvaluation = attendanceEvaluations.FirstOrDefault(p => p.Date == theDay);

                // 获取正在提交中的评估修改申请
                var modifyAttendanceApplication = modifyAttendanceApplications.FirstOrDefault(p => p != null && p.Date == theDay);
                var canApplyModify = (modifyAttendanceApplication == null);
                var applyModifyStr = modifyAttendanceApplication.GetCurrentApplicationString();
                
                //修改历史
                var modifyHistoryStr = modifyHistorys
                                            .FirstOrDefault(p => p.Date == theDay)
                                            .GetLatestModifyHistroyString();
                var evaluationStatus = attendanceEvaluation.GetEvaluationStatusString();
                var simpleEvaluationStatus = attendanceEvaluation.GetSimpleEvaluationStatusString();
                var evaluationClassName = attendanceEvaluation.GetEvaluationStatusClassName();

                //是否是当天
                var isToday = false;
                if (theDay == DateTime.Now.Date)
                {
                    isToday = true;
                };
                var attendanceTheDayInfo = new
                {
                    theDay,
                    onDutyList =
                        attendanceEvaluation.DayAttendanceInfoList.Where(
                            p => p.AttendanceType == AttendanceType.onDuty),
                    
                    offDutyList =
                        attendanceEvaluation.DayAttendanceInfoList.Where(
                            p => p.AttendanceType == AttendanceType.offDuty),
                    
                    leaveModel = attendanceEvaluation.LeaveInfo,
                    evaluationStatus,
                    remarkInfo,
                    canApplyModify,
                    isToday
                };

                var infoForCalendar = new
                {
                    theDayInfo,
                    simpleEvaluationStatus,
                    applyModifyStr,
                    modifyHistoryStr,
                    evaluationClassName
                };

                infoForCalendarList.Add(infoForCalendar);
                attendanceInfoPerDayList.Add(attendanceTheDayInfo);

            }
            monthAttendanceInfoList.Add(infoForCalendarList);
            monthAttendanceInfoList.Add(attendanceInfoPerDayList);

            LogEx.TRACE("AttendanceController - PersonalAttendanceInfoListPerMonth", "。。。请求拿一个用户一个月的考勤记录结束");
            return Json(monthAttendanceInfoList, JsonRequestBehavior.AllowGet);
        }







        #endregion

        #region [ private method ]

        private DateTime getDateByDefault(long? time)
        {
            var date = DateTime.Now.Date;
            if (time.HasValue)
            {
                date = EpochDateTimeExtension.FromEpoch(time.Value);
            }
            return date;
        }

        private List<DayAttendanceInfoModel> findAttendanceInfoFromList(
            IEnumerable<AttendanceInfo> attendanceInfoList,
            DateTime theDay,
            AttendanceType? attendanceType = null,
            bool isAbnormal = false
            )
        {
            if (attendanceInfoList == null) throw new ArgumentNullException("attendanceInfoList");
            var query = attendanceInfoList.Where(p =>
                        p.Date.Day == theDay.Day &
                        p.IsAbnormalAttendance == isAbnormal
                    );
            if (attendanceType != null)
            {
                query = query.Where(
                    p => p.AttendanceType == attendanceType
                    );
            }
            var attendanceInfoOfTheDay = query.ToList();
            return convertAttendanceInfoToDayInfoToModel(attendanceInfoOfTheDay);
        }


        private List<SimpleLeaveInfo> convertLeaveInfoListToSimpleModel(List<LeaveInfo> leaveInfoList)
        {
            var simpleLeaveInfoList = new List<SimpleLeaveInfo>();
            leaveInfoList.ForEach(
                p => simpleLeaveInfoList.Add(new SimpleLeaveInfo(p, AttendanceService))
                );
            return simpleLeaveInfoList;
        }


        private AttendanceStatus getDefaultAttendanceStatus()
        {
            return AttendanceService.GetDefaultAttendanceStatus(CurrentUserId, DateTime.Now).Result;
        }


        private List<DayAttendanceInfoModel> convertAttendanceInfoToDayInfoToModel(List<AttendanceInfo> attendanceInfoList)
        {
            var dayAttendanceInfoModel = new List<DayAttendanceInfoModel>();
            attendanceInfoList.ForEach(p => dayAttendanceInfoModel.Add(new DayAttendanceInfoModel(p)));
            return dayAttendanceInfoModel;
        }

        private static List<AttendanceInfoModel> convertAttendanceInfoListToModel(List<AttendanceInfo> attendanceInfoList)
        {
            var attendanceJsonModel = new List<AttendanceInfoModel>();
            attendanceInfoList.ForEach(p => attendanceJsonModel.Add(new AttendanceInfoModel(p)));
            return attendanceJsonModel;
        }

        private bool IsHasPermisson(String permissionStr, Guid userId)
        {
            var isHasPermisson = EzApiClient.UserHasPermission(permissionStr, userId);
            return isHasPermisson;
        }

        #endregion
    }

}
